home *** CD-ROM | disk | FTP | other *** search
- #include <windows.h>
- #pragma hdrstop
- #include <string.h>
- #include <assert.h>
- #include "level.h"
- //---------------------------------------------------------------------------
- /*
-
- POZOR!
- velikost zßsobnφku nastavte na 256MB (v Project/Settings/Linker/Output)
- velikost swapovacφho souboru nastavte na 1200MB (Ovlßdacφ panely/SystΘm/Up°esnit/Mo₧nosti v²konu)
-
- Pam∞¥
- posTable: (18+Nobj)*maxPos
- hashTable: 8*maxPos
- movedObj: Nobj*48*maxPos
- */
-
- struct Move {
- Psquare obj,next; //odkud kam se p°esouvß
- short dist; //vzdßlenost mezi hrßΦem a obj
- short direct; //sm∞r p°esunu
- };
- typedef Move *PMove;
-
- int DXY=1; //2 pro vφce ne₧ 256 polφ, jinak 1
-
- int
- Nobj, //poΦet objekt∙
- Nstore, //poΦet ·lo₧iÜ¥
- Nground, //poΦet polφΦek, kde nenφ ze∩
- posSize, //dΘlka pozice bez hlaviΦky (v bytech)
- posSize1, //jako posSize, ale sni₧uje se p°i testBlocked
- posSize2, //alokovanß dΘlka na pozici v posTable
- DHDR, //dΘlka hlaviΦky p°ed pozicφ
- distId, //ka₧dΘ volßnφ findObjects pou₧ije jinΘ id
- maxPos, //max. poΦet prohledßvan²ch pozic
- maxPos0=5000000,//omezenφ maxPos
- maxMem=900, //omezenφ adresovΘho prostroru (MB)
- DhashTable, //dΘlka hashovacφ tabulky
- algorithm, //0=do hloubky, 1=do Üφ°ky, 2=dijkstra, 3=gener
- testing, //byl zmenÜen poΦet objekt∙ uvnit° testBlocked
- finalDone, //poΦet objekt∙ na ·lo₧iÜtφch
- *finalDistA;//pole pro vÜechny finalDists
-
- Pchar
- *hashTable, //hashovacφ tabulka prohledan²ch pozic
- *hashTablek,//konec hashovacφ tabulky
- UfoundPos, //nalezenß koncovß pozice
- UfoundPosD,
- posTable, //pam∞¥ na vÜechny prohledanΘ pozice
- posTablek,
- UposTable, //ukazatel na volnΘ mφsto v posTable
- UfoundSol, //ukazatel na konec °eÜenφ
- firstMove, //tahy vzniklΘ smazßnφm slep²ch uliΦek
- UfirstMove,
- finalPos; //koncovß pozice (bez hrßΦe)
-
- PMove
- movedObj; //pam∞¥ pro Move
-
- Psquare
- *distBuf1,*distBuf2, //pomocnΘ buffery pro findDist a findObjects
- *i2p, //p°evod Φφsla polφΦka na ukazatel
- *fin2p; //ukazatele na ·lo₧iÜt∞ (v po°adφ, v jakΘm se zaplnφ)
-
- //hlaviΦka pozice p°i prohledßvßnφ do hloubky
- struct Hdr2 {
- Pchar parent;
- int eval;
- PMove lastMove;
- short dist;
- };
- const int DHDR2= 14;
-
- //hlaviΦka pozice p°i prohledßvßnφ do Üφ°ky
- struct Hdr3 {
- Pchar parent;
- short mov,pus;
- PMove movesBeg,movesEnd;
- bool dual;
- };
- const int DHDR3= 17;
-
- //hlaviΦka pozice p°i Dijkstrov∞ algoritmu
- struct Hdr1 {
- Pchar parent;
- int eval;
- int heapItem;
- PMove lastMove;
- bool dual;
- };
- const int DHDR1= 17;
-
- //hlaviΦka pozice p°i generovßnφ zadßnφ
- struct Hdr4 {
- short mov,pus;
- PMove movesBeg,movesEnd;
- };
- const int DHDR4= 12;
-
- typedef Hdr1 *PHdr1;
- typedef Hdr2 *PHdr2;
- typedef Hdr3 *PHdr3;
- typedef Hdr4 *PHdr4;
- #define HDR1(p) ((Hdr1*)(p-DHDR1))
- #define HDR2(p) ((Hdr2*)(p-DHDR2))
- #define HDR3(p) ((Hdr3*)(p-DHDR3))
- #define HDR4(p) ((Hdr4*)(p-DHDR4))
-
- Pchar backtrack(PMove Umoves, int movpus) ;
-
- //-------------------------------------------------------------------
- inline void wrXY0(Pchar p, int i)
- {
- if(DXY==1) *((BYTE*)p) = (BYTE)i;
- else *((WORD*)p) = (WORD)i;
- }
-
- inline void wrXY(Pchar &p, int i)
- {
- if(DXY==1) *((BYTE*)p) = (BYTE)i, p++;
- else *((WORD*)p) = (WORD)i, p+=2;
- }
-
- inline int rdXY(void *p)
- {
- if(DXY==1) return *((BYTE*)p);
- else return *((WORD*)p);
- }
-
- void noMem()
- {
- msg(lng(768,"Not enough memory"));
- }
- //-------------------------------------------------------------------
- //nalezenφ nejkratÜφ cesty mezi src a dest (bez p°esunu beden)
- //do polφ zapφÜe hodnoty dist, distId
- void findDist(Psquare src, Psquare dest)
- {
- int i,d;
- Psquare *p1,*p2,pn;
-
- distId++;
- src->distId=distId;
- src->dist=0;
- distBuf1[0]=src;
- distBuf1[1]=0;
- for(d=1; ; d++){
- if(d&1) p1=distBuf1,p2=distBuf2;
- else p1=distBuf2,p2=distBuf1;
- if(!*p1) break;
- for( ; *p1; p1++){
- for(i=0; i<4; i++){
- pn= nxtP(*p1,i);
- if(pn->distId!=distId){
- if(pn->obj==BM_GROUND){
- pn->distId=distId;
- pn->dist=d;
- *p2++=pn;
- }else{
- pn->dist=MAXDIST;
- }
- }
- }
- if(*p1==dest) return;
- }
- *p2=0;
- }
- }
- //-------------------------------------------------------------------
- #ifndef NDEBUG
- int testPos(Pchar prevPos)
- {
- Pchar v;
- int i;
- Psquare p;
-
- for(v=prevPos+DXY; v<prevPos+posSize1; v+=DXY){
- i=rdXY(v);
- for(p=board; p->i!=i || p->obj!=BM_OBJECT; p++){
- if(p==boardk){
- return 0;
- }
- }
- }
- for(v=prevPos+2*DXY; v<prevPos+posSize1; v+=DXY){
- if(rdXY(v)<=rdXY(v-DXY)) return 0;
- }
- return 1;
- }
- #endif
- //-------------------------------------------------------------------
- #define finOrWall(p) ((p)->obj!=BM_WALL && !(p)->store)
-
- int testDead(Psquare p)
- {
- Psquare pU,pD,pU2,pD2;
-
- pU=nxtP(p,2); pU2=nxtP(pU,2);
- pD=nxtP(p,3); pD2=nxtP(pD,3);
- if((p+1)->obj!=BM_GROUND){
- if(pD->obj!=BM_GROUND){
- if((pD+1)->obj!=BM_GROUND)
- if(!p->store || finOrWall(p+1) || finOrWall(pD) || finOrWall(pD+1)) return 1;
- if((pD+2)->obj!=BM_GROUND && (pD2+1)->obj!=BM_GROUND && (pD2+2)->obj!=BM_GROUND)
- if(!(pD+1)->store && !p->store) return 1;
- }else{
- if((pD2)->obj!=BM_GROUND){
- if((pD-1)->obj!=BM_GROUND &&
- (pD+1)->obj!=BM_GROUND && (pD2-1)->obj!=BM_GROUND
- || (pD2+1)->obj!=BM_GROUND && (pD-1)->obj==BM_WALL &&
- (pD+2)->obj==BM_WALL && !(pD+1)->store)
- if(!(pD)->store && !p->store) return 1;
- }
- }
- if(pU->obj!=BM_GROUND){
- if((pU+1)->obj!=BM_GROUND)
- if(!p->store || finOrWall(p+1) || finOrWall(pU) || finOrWall(pU+1)) return 1;
- if((pU+2)->obj!=BM_GROUND && (pU2+1)->obj!=BM_GROUND && (pU2+2)->obj!=BM_GROUND)
- if(!(pU+1)->store && !p->store) return 1;
- }else{
- if((pU2)->obj!=BM_GROUND){
- if((pU+1)->obj!=BM_GROUND &&
- (pU-1)->obj!=BM_GROUND && (pU2-1)->obj!=BM_GROUND
- || (pU2+1)->obj!=BM_GROUND && (pU-1)->obj==BM_WALL &&
- (pU+2)->obj==BM_WALL && !(pU+1)->store)
- if(!(pU)->store && !p->store) return 1;
- }
- }
- }else{
- if((p+2)->obj!=BM_GROUND){
- if(((pD)->obj!=BM_GROUND && (pD+2)->obj!=BM_GROUND &&
- (pU+1)->obj==BM_WALL && (pD2+1)->obj==BM_WALL && !(pD+1)->store
- || (pU)->obj!=BM_GROUND && (pU+2)->obj!=BM_GROUND &&
- (pD+1)->obj==BM_WALL && (pU2+1)->obj==BM_WALL && !(pU+1)->store)
- || (pU+1)->obj!=BM_GROUND && (pD+1)->obj!=BM_GROUND &&
- ((pU)->obj!=BM_GROUND && (pD+2)->obj!=BM_GROUND ||
- (pD)->obj!=BM_GROUND && (pU+2)->obj!=BM_GROUND))
- if(!(p+1)->store && !p->store) return 1;
- }
- }
- if((p-1)->obj!=BM_GROUND){
- if(pD->obj!=BM_GROUND){
- if((pD-1)->obj!=BM_GROUND)
- if(!p->store || finOrWall(p-1) || finOrWall(pD) || finOrWall(pD-1)) return 1;
- if((pD-2)->obj!=BM_GROUND && (pD2-1)->obj!=BM_GROUND && (pD2-2)->obj!=BM_GROUND)
- if(!(pD-1)->store && !p->store) return 1;
- }else{
- if((pD2)->obj!=BM_GROUND){
- if((pD+1)->obj!=BM_GROUND &&
- (pD-1)->obj!=BM_GROUND && (pD2+1)->obj!=BM_GROUND
- || (pD2-1)->obj!=BM_GROUND && (pD+1)->obj==BM_WALL &&
- (pD-2)->obj==BM_WALL && !(pD-1)->store)
- if(!(pD)->store && !p->store) return 1;
- }
- }
- if(pU->obj!=BM_GROUND){
- if((pU-1)->obj!=BM_GROUND)
- if(!p->store || finOrWall(p-1) || finOrWall(pU) || finOrWall(pU-1)) return 1;
- if((pU-2)->obj!=BM_GROUND && (pU2-1)->obj!=BM_GROUND && (pU2-2)->obj!=BM_GROUND)
- if(!(pU-1)->store && !p->store) return 1;
- }else{
- if((pU2)->obj!=BM_GROUND){
- if((pU+1)->obj!=BM_GROUND &&
- (pU-1)->obj!=BM_GROUND && (pU2+1)->obj!=BM_GROUND
- || (pU2-1)->obj!=BM_GROUND && (pU+1)->obj==BM_WALL &&
- (pU-2)->obj==BM_WALL && !(pU-1)->store)
- if(!(pU)->store && !p->store) return 1;
- }
- }
- }else{
- if((p-2)->obj!=BM_GROUND){
- if(((pD)->obj!=BM_GROUND && (pD-2)->obj!=BM_GROUND &&
- (pU-1)->obj==BM_WALL && (pD2-1)->obj==BM_WALL && !(pD-1)->store
- || (pU)->obj!=BM_GROUND && (pU-2)->obj!=BM_GROUND &&
- (pD-1)->obj==BM_WALL && (pU2-1)->obj==BM_WALL && !(pU-1)->store)
- || (pU-1)->obj!=BM_GROUND && (pD-1)->obj!=BM_GROUND &&
- ((pU)->obj!=BM_GROUND && (pD-2)->obj!=BM_GROUND ||
- (pD)->obj!=BM_GROUND && (pU-2)->obj!=BM_GROUND))
- if(!(p-1)->store && !p->store) return 1;
- }
- }
- return 0;
- }
- //-------------------------------------------------------------------
- //nalezenφ dosa₧iteln²ch objekt∙ a vygenerovßnφ tah∙
- PMove findObjects(PMove Umoves)
- {
- Psquare pn,pnn,*p1,*p2;
- int i,d;
-
- distId++;
- mover->distId=distId;
- mover->dist=0;
- distBuf1[0]=mover;
- distBuf1[1]=0;
- for(d=1; ; d++){
- if(d&1) p1=distBuf1,p2=distBuf2;
- else p1=distBuf2,p2=distBuf1;
- if(!*p1) break;
- for( ; *p1; p1++){
- for(i=0; i<4; i++){
- pn= nxtP(*p1,i);
- if(pn->distId!=distId && pn->obj==BM_GROUND){
- pn->distId=distId;
- pn->dist=d;
- *p2++=pn;
- }
- else if(pn->obj==BM_OBJECT){
- pnn= nxtP(pn,i);
- if(pnn->obj==BM_GROUND && pnn->finalDist<MAXDIST){
- Umoves->obj=pn;
- Umoves->next=pnn;
- Umoves->dist=(short)d;
- Umoves->direct=(short)i;
- Umoves++;
- }
- }
- }
- }
- *p2=0;
- }
- return Umoves;
- }
- //-------------------------------------------------------------------
- PMove findObjectsR(PMove Umoves)
- {
- Psquare pn,pnn,*p1,*p2;
- int i,d;
-
- distId++;
- mover->distId=distId;
- mover->dist=0;
- distBuf1[0]=mover;
- distBuf1[1]=0;
- for(d=1; ; d++){
- if(d&1) p1=distBuf1,p2=distBuf2;
- else p1=distBuf2,p2=distBuf1;
- if(!*p1) break;
- for( ; *p1; p1++){
- for(i=0; i<4; i++){
- pn= nxtP(*p1,i);
- if(pn->distId!=distId && pn->obj==BM_GROUND){
- pn->distId=distId;
- pn->dist=d;
- *p2++=pn;
- }
- else if(pn->obj==BM_OBJECT){
- pnn= prvP(*p1,i);
- if(pnn->obj==BM_GROUND){
- Umoves->obj=pn;
- Umoves->next=*p1;
- Umoves->dist=(short)d;
- Umoves->direct=(short)i;
- Umoves++;
- }
- }
- }
- }
- *p2=0;
- }
- return Umoves;
- }
- //-------------------------------------------------------------------
- PMove findObjectsD(PMove Umoves, Psquare o, int dir)
- {
- Psquare pn,pnn,*p1,*p2;
- int i,d;
- bool found;
-
- distId++;
- mover->distId=distId;
- mover->dist=0;
- distBuf1[0]=mover;
- distBuf1[1]=0;
- for(d=1; ; d++){
- if(d&1) p1=distBuf1,p2=distBuf2;
- else p1=distBuf2,p2=distBuf1;
- if(!*p1) break;
- for( ; *p1; p1++){
- found=false;
- for(i=0; i<4; i++){
- pn= nxtP(*p1,i);
- if(pn->distId!=distId && pn->obj==BM_GROUND){
- pn->distId=distId;
- pn->dist=d;
- *p2++=pn;
- }
- else if(pn->obj==BM_OBJECT){
- pnn= prvP(*p1,i);
- if(pnn->obj==BM_GROUND){
- found=true;
- }
- }
- }
- if(found){
- Umoves->next=*p1;
- Umoves->dist=(short)d;
- Umoves->obj=o;
- Umoves->direct=(short)dir;
- Umoves++;
- }
- }
- *p2=0;
- }
- return Umoves;
- }
- //-------------------------------------------------------------------
- void makeMove(Pchar newPos, Pchar prevPos, Move &curMove)
- {
- Pchar v,v1;
-
- memcpy(newPos,prevPos,posSize);
- //nalezni posledn∞ p°esunut² objekt
- for(v=newPos+DXY; rdXY(v)!=curMove.obj->i; v+=DXY) ;
- //set°id pozici
- if(curMove.next->i < curMove.obj->i){
- for(v1=v-DXY; rdXY(v1)>curMove.next->i && v1>newPos; v1-=DXY){
- wrXY0(v1+DXY,rdXY(v1));
- }
- wrXY0(v1+DXY,curMove.next->i);
- }
- else{
- for(v1=v+DXY; v1<newPos+posSize1 && rdXY(v1)<curMove.next->i; v1+=DXY){
- wrXY0(v1-DXY,rdXY(v1));
- }
- wrXY0(v1-DXY,curMove.next->i);
- }
- //pozice hrßΦe
- wrXY0(newPos,curMove.obj->i);
- assert(testPos(newPos));
- }
- //-------------------------------------------------------------------
- //v²poΦet hashovacφ funkce
- Pchar *hash(Pchar pos)
- {
- DWORD h;
- Pchar posEnd;
-
- h=0;
- posEnd= pos+posSize1;
- for( ; pos<posEnd; pos++){
- h= (h + (DWORD)*(Puchar)pos)*1234567;
- // h= h = (h << 5) + h + *(Puchar)pos;
- }
- return &hashTable[h%DhashTable];
- }
- //-------------------------------------------------------------------
- //p°ed touto funkcφ musφ b²t zavolßno findObjects
- int testBlocked(Pchar prevPos, PMove lastMove, PMove Umoves)
- {
- Psquare p,p0,pn,*p1,*p2;
- Pchar curPos,v1,v2,found,w;
- int i,d,posSize0,result,finalDone0;
-
- if(!lastMove) return 0;
- //podφvej se okolo poslednφho tahu
- p0=lastMove->next;
- p1=distBuf1;
- for(i=0; i<8; i++){
- p=nxtP(p0,i);
- if(p->obj==BM_GROUND && p->distId!=distId){
- *p1++=p;
- p->distId=distId+1;
- }
- }
- if(p1-distBuf1==0) return 0;
- if(UposTable==posTablek) return 0;
- *p1=0;
- //najdi objekty sousedφcφ s nedosa₧itelnou oblastφ
- distId++;
- for(d=1; ; d++){
- if(d&1) p1=distBuf1,p2=distBuf2;
- else p1=distBuf2,p2=distBuf1;
- if(!*p1) break;
- for( ; *p1; p1++){
- for(i=0; i<8; i++){
- pn= nxtP(*p1,i);
- if(pn->distId!=distId){
- if(pn->obj==BM_OBJECT){
- pn->distId=distId;
- }
- else if(pn->obj==BM_GROUND && i<4){
- pn->distId=distId;
- *p2++=pn;
- }
- }
- }
- }
- *p2=0;
- }
- //testovacφ pozice zapisuj od konce alokovanΘ pam∞ti
- if(!testing){
- w=posTablek;
- posTablek=UposTable-posSize2;
- UposTable= w-posSize2;
- posSize2= -posSize2;
- }
- //vytvo° novou pozici, kterß mß mΘn∞ objekt∙
- curPos= UposTable;
- v2=curPos+DXY;
- for(v1=prevPos+DXY; v1<prevPos+posSize1; v1+=DXY){
- p=i2p[rdXY(v1)];
- if(p->distId==distId){
- wrXY(v2,p->i);
- }else{
- p->obj=BM_GROUND;
- #ifdef DEBUG
- paintSquare(p);
- #endif
- }
- }
- //sni₧ posSize1
- posSize0=posSize1;
- posSize1=(int)(v2-curPos);
- result=0;
- if(posSize1<posSize0){
- if(posSize1>2*DXY){
- while(v2!=curPos+posSize){
- wrXY(v2,-1);
- }
- //spus¥ backtracking
- HDR2(curPos)->parent=0;
- HDR2(curPos)->eval=0;
- HDR2(curPos)->lastMove=0;
- finalDone0=finalDone;
- testing++;
- #ifdef DEBUG
- repaint();
- Sleep(10);
- #endif
- found= backtrack(Umoves,0);
- if(found){
- HDR2(found)->parent=curPos;
- }else{
- //pozice je ne°eÜitelnß nebo moc slo₧itß
- result=1;
- }
- testing--;
- finalDone=finalDone0;
- }
- //vra¥ zpßtky vÜechny objekty
- posSize1=posSize0;
- for(v1=prevPos+DXY; v1<prevPos+posSize1; v1+=DXY){
- assert(rdXY(v1)>=0 && rdXY(v1)<width*height);
- i2p[rdXY(v1)]->obj=BM_OBJECT;
- #ifdef DEBUG
- paintSquare(i2p[rdXY(v1)]);
- #endif
- }
- }
- if(!testing){
- posSize2= -posSize2;
- w=posTablek;
- posTablek=UposTable+posSize2;
- UposTable= w+posSize2;
- }
- return result;
- }
- //-------------------------------------------------------------------
- /*
-
- p°φklad cont pro direct==1
-
- . X X X X X X X X
- -1 0 1 1 2 0 1 1 X
- . X X X . X X X X
-
- */
-
- //protlaΦenφ objektu zkrz celou chodbu
- PMove testLastMove(PMove lastMove, PMove Umoves)
- {
- if(lastMove && lastMove->next->cont[lastMove->direct]>0){
- Psquare p=nxtP(lastMove->next, lastMove->direct);
- if(p->obj==BM_GROUND && p->finalDist<MAXDIST){
- //tlaΦenφ objektu ve stejnΘm sm∞ru jako p°edchozφ tah
- Umoves->obj= lastMove->next;
- Umoves->next= p;
- Umoves->dist=1;
- Umoves->direct= lastMove->direct;
- Umoves++;
- }
- return Umoves;
- }
- return 0;
- }
-
- PMove testLastMoveR(PMove lastMove, PMove Umoves)
- {
- if(lastMove && lastMove->next->cont[lastMove->direct^1]==1){
- Psquare p=prvP(lastMove->next, lastMove->direct);
- Psquare pn=prvP(p,lastMove->direct);
- assert(p->obj==BM_GROUND);
- assert(lastMove->obj->obj==BM_GROUND);
- assert(lastMove->next->obj==BM_OBJECT);
- if(pn->obj==BM_GROUND){
- //ta₧enφ objektu ve stejnΘm sm∞ru jako p°edchozφ tah
- Umoves->obj= lastMove->next;
- Umoves->next= p;
- Umoves->dist=1;
- Umoves->direct= lastMove->direct;
- Umoves++;
- }
- return Umoves;
- }
- return 0;
- }
-
- void testLastMoveD(PMove lastMove, PMove Umoves, PMove UmovesEnd)
- {
- if(!lastMove) return;
- Psquare pm= prvP(lastMove->obj,lastMove->direct);
- if(pm->cont[lastMove->direct^1]==1){
- Psquare p=prvP(pm, lastMove->direct);
- assert(p->obj==BM_GROUND);
- assert(lastMove->obj->obj==BM_GROUND);
- assert(pm->obj==BM_OBJECT);
- for(PMove m=Umoves; m<UmovesEnd; m++){
- if(m->obj!=pm || m->direct!=lastMove->direct) m->direct=-1;
- }
- }
- }
- //-------------------------------------------------------------------
- Pchar backtrack(PMove Umoves, int movpus)
- {
- Pchar *u,v,newPos,prevPos,found,result=0;
- int m,o,i,f1,f2,movpus1,finalDone0,direct0;
- PMove UmovesEnd,um,bm;
- Psquare mover0,*newMover,p,pn;
- Move curMove;
-
- prevPos=UposTable;
- mover0=mover;
- finalDone0=finalDone;
- //najdi dosa₧itelnΘ objekty
- UmovesEnd= findObjects(Umoves);
- //hrßΦe umφsti do levΘho hornφho rohu
- for(newMover=i2p; (*newMover)->distId!=distId; newMover++) ;
- //do pozice zapiÜ polohu hrßΦe
- wrXY0(prevPos,(*newMover)->i);
- //ukonΦi testBlocked jakmile se lze dostat k objekt∙m ze vÜech stran
- if(testing){
- for(v=prevPos+posSize1-DXY; v>prevPos; v-=DXY){
- p=i2p[rdXY(v)];
- if(!p->store){
- for(i=0; i<4; i++){
- pn=nxtP(p,i);
- if(pn->obj==BM_GROUND && pn->distId!=distId) goto l1;
- }
- }
- }
- return prevPos;
- }
- l1:
- //vypoΦti hashovacφ funkci
- u= hash(prevPos);
- //p°idej novou pozici do tabulky
- for( ;*u; ){
- if(!memcmp(*u,prevPos,posSize)){
- if(testing && HDR2(*u)->parent){
- //pozice je °eÜitelnß
- return *u;
- }
- //neprohledßvej stejnou pozici vφcekrßt
- return 0;
- }
- u++;
- if(u==hashTablek) u=hashTable;
- }
- *u=prevPos;
- UposTable+=posSize2;
- //protlaΦ objekt celou chodbou
- um=testLastMove(HDR2(prevPos)->lastMove, Umoves);
- if(um) UmovesEnd=um;
- //zjisti, jestli poslednφ tah n∞co nezablokoval
- if(testBlocked(prevPos, HDR2(prevPos)->lastMove, UmovesEnd)) return 0;
- //vyzkouÜej postupn∞ vÜechny mo₧nΘ p°esuny
- for( ; Umoves<UmovesEnd; Umoves++){
- newPos=UposTable;
- if(newPos==posTablek) break; //pam∞¥ u₧ je plnß
- bm=Umoves;
- if(0+testing){
- //zvol p°esun sm∞rem do zablokovanΘho prostoru
- m=-1;
- for(um=Umoves; um<UmovesEnd; um++){
- for(i=0; i<4; i++){
- p=nxtP(um->obj,i);
- if(p->obj==BM_GROUND && distId - p->distId > m){
- m = distId - p->distId;
- bm=um;
- }
- }
- }
- }else{
- //vyber objekt, kter² je nejblφ₧e ·lo₧iÜti
- m=0x7fffffff;
- for(um=Umoves; um<UmovesEnd; um++){
- f1= um->obj->finalDists[finalDone];
- f2= um->next->finalDists[finalDone];
- o= (f2<<2) + ((f2-f1)<<5) + um->dist;
- if(um->obj->direct == (um->direct^1)) o+=600;
- if(o<m){
- m=o;
- bm=um;
- }
- }
- }
- curMove=*bm;
- *bm=*Umoves;
- movpus1= movpus+curMove.dist+1;
- //prove∩ jeden p°esun
- curMove.next->obj= BM_OBJECT;
- curMove.obj->obj= BM_GROUND;
- if(testDead(curMove.next)){
- curMove.next->obj= BM_GROUND;
- curMove.obj->obj= BM_OBJECT;
- }else{
- #ifdef DEBUG
- mover=0;
- paintSquare(curMove.next);
- paintSquare(curMove.obj);
- Sleep(20);
- #endif
- mover=curMove.obj;
- direct0= curMove.next->direct;
- curMove.next->direct= curMove.direct;
- //vytvo° novou pozici
- HDR2(newPos)->parent=0;
- HDR2(newPos)->eval= movpus1;
- HDR2(newPos)->lastMove= &curMove;
- makeMove(newPos,prevPos,curMove);
- //porovnej novou pozici s koncovou pozicφ
- amax(finalDone, curMove.obj->finalDist);
- if(curMove.next->finalDist==finalDone){
- do{
- finalDone++;
- }while(fin2p[finalDone]->obj==BM_OBJECT);
- }
- if(!testing && finalDone==Nstore){
- UfoundPos= newPos;
- HDR2(newPos)->eval=movpus1;
- HDR2(newPos)->parent=prevPos;
- UposTable+=posSize2;
- result=prevPos;
- }else{
- //backtracking
- found=backtrack(UmovesEnd, movpus1);
- if(found){
- HDR2(found)->parent= prevPos;
- assert(testing || HDR2(found)->eval==movpus1);
- HDR2(found)->dist= (short) (curMove.dist+1);
- result=prevPos;
- }
- }
- //vra¥ zp∞t vÜechny zm∞ny
- curMove.next->obj= BM_GROUND;
- curMove.obj->obj= BM_OBJECT;
- #ifdef DEBUG
- mover=0;
- paintSquare(curMove.next);
- paintSquare(curMove.obj);
- #endif
- curMove.next->direct= direct0;
- mover=mover0;
- finalDone=finalDone0;
- if(result) break;
- }
- }
- return result;
- }
- //-------------------------------------------------------------------
- void depthSearch()
- {
- int m=mover->i;
- //p°iprav poΦßteΦnφ pozici
- PHdr2 hdr= HDR2(UposTable);
- hdr->parent=0;
- hdr->eval=0;
- hdr->lastMove=0;
- while(fin2p[finalDone]->obj==BM_OBJECT) finalDone++;
- //spus¥ backtracking
- backtrack(movedObj,0);
- //obnov poΦßteΦnφ pozici hrßΦe
- wrXY0(posTable+DHDR2, m);
- }
- //-------------------------------------------------------------------
- void breadthSearch()
- {
- Pchar *u,v,curPos,newPos;
- char *movedObjBeg,*m;
- PHdr3 curPosHdr,newPosHdr,found;
- PMove Umoves,Umoves1,um;
- Psquare p,pn,*pp;
- int i,j;
- bool isDual;
-
- //poΦßteΦnφ pozice
- curPos=UposTable;
- curPosHdr=HDR3(curPos);
- curPosHdr->parent=0;
- curPosHdr->mov=curPosHdr->pus=0;
- curPosHdr->movesBeg= movedObj;
- curPosHdr->movesEnd= Umoves= findObjects(movedObj);
- curPosHdr->dual= false;
- UposTable+=posSize2;
-
-
- ///
- /*
- memcpy(posTable+posSize2,posTable,posSize2);
- findDist(i2p[rdXY(posTable+DHDR)],0);
- for(pp=i2p; (*pp)->distId!=distId; pp++) ;
- wrXY0(UposTable,(*pp)->i);
- newPosHdr=HDR3(UposTable);
- newPosHdr->mov=(short)(*pp)->dist;
- u=hash(UposTable);
- assert(!*u);
- *u=UposTable;
- UposTable+=posSize2;
- */
-
-
- //sma₧ vÜechny objekty
- for(v=curPos+DXY; v<curPos+posSize1; v+=DXY){
- assert(i2p[rdXY(v)]->obj==BM_OBJECT);
- i2p[rdXY(v)]->obj=BM_GROUND;
- }
- //koncovß pozice
- for(i=0; i<Nstore; i++){
- assert(fin2p[i]->obj==BM_GROUND);
- fin2p[i]->obj=BM_OBJECT;
- }
-
- ///curPos=UposTable;
-
-
- //vφce koncov²ch pozic podle umφst∞nφ hrßΦe
- for(p=board; p<boardk; p++){
- p->distId=0;
- }
- for(j=0; j<Nstore; j++){
- p=fin2p[j];
- for(i=0; i<4; i++){
- pn=nxtP(p,i);
- if(!pn->distId && pn->obj==BM_GROUND){
- findDist(pn,0);
- for(pp=i2p; (*pp)->distId!=distId; pp++) ;
- memcpy(UposTable+DXY,finalPos,posSize1-DXY);
- wrXY0(UposTable,(*pp)->i);
- UposTable+=posSize2;
- }
- }
- }
- for(v=curPos+posSize2; v<UposTable; v+=posSize2){
- newPosHdr=HDR3(v);
- newPosHdr->parent=0;
- newPosHdr->mov=curPosHdr->pus=0;
- newPosHdr->dual= true;
- newPosHdr->movesBeg= Umoves;
- mover=i2p[rdXY(v)];
- newPosHdr->movesEnd= findObjectsR(Umoves);
- ///
- for(um=Umoves; um<newPosHdr->movesEnd; um++) um->dist=1;
-
- Umoves= newPosHdr->movesEnd;
- }
- //sma₧ vÜechny objekty
- for(i=0; i<Nstore; i++){
- assert(fin2p[i]->obj==BM_OBJECT);
- fin2p[i]->obj=BM_GROUND;
- }
- movedObjBeg=(char*)movedObj+65536;
- //cyklus p°es vÜechny nalezenΘ pozice
- for( ;curPos<UposTable; curPos+=posSize2){
- curPosHdr= HDR3(curPos);
- isDual= curPosHdr->dual;
- //vytvo° aktußlnφ pozici
- for(v=curPos+DXY; v<curPos+posSize1; v+=DXY){
- assert(i2p[rdXY(v)]->obj==BM_GROUND);
- i2p[rdXY(v)]->obj=BM_OBJECT;
- }
- //uvolni tahy, kterΘ u₧ byly zpracovßny
- m= (char*)( (int)curPosHdr->movesBeg & -65536 );
- i= m-movedObjBeg;
- if(i>5000000){
- VirtualFree(movedObjBeg,i,MEM_DECOMMIT);
- movedObjBeg=m;
- }
- //vyzkouÜej vÜechny mo₧nΘ p°esuny
- for(Umoves1=curPosHdr->movesBeg; Umoves1<curPosHdr->movesEnd && Umoves1->direct>=0; Umoves1++){
- Move &curMove= *Umoves1;
- newPos=UposTable;
- if(newPos==posTablek) break;
- newPosHdr=HDR3(newPos);
- //prove∩ tah
- assert(testPos(curPos));
- assert(curMove.next->obj==BM_GROUND);
- assert(curMove.obj->obj==BM_OBJECT);
- curMove.next->obj= BM_OBJECT;
- curMove.obj->obj= BM_GROUND;
- if(isDual || !testDead(curMove.next)){
- //vytvo° novou pozici
- mover= isDual ? prvP(curMove.next,curMove.direct) : curMove.obj;
- makeMove(newPos,curPos,curMove);
- newPosHdr->mov= (short)(curPosHdr->mov + curMove.dist);
- newPosHdr->pus= (short)(curPosHdr->pus + 1);
- newPosHdr->dual= isDual;
- //najdi vÜechny mo₧nΘ p°esuny v novΘ pozici
- newPosHdr->movesEnd= isDual ? findObjectsR(Umoves) : findObjects(Umoves);
- //hrßΦe dej do levΘho hornφho rohu
- for(pp=i2p; (*pp)->distId!=distId; pp++) ;
- wrXY0(newPos,(*pp)->i);
- //vypoΦti hashovacφ funkci
- u=hash(newPos);
- for(;;){
- if(!*u){
- //p°idej novou pozici do tabulky
- *u=newPos;
- UposTable+=posSize2;
- newPosHdr->parent= curPos;
- newPosHdr->movesBeg= Umoves;
- if(1 || !isDual){ ///
- um= (isDual ? testLastMoveR:testLastMove)(&curMove, Umoves);
- if(um) um->direct=-1;
- }
- if(!isDual && testBlocked(newPos, &curMove, newPosHdr->movesEnd)){///
- //pozice nebude mφt ₧ßdnΘ tahy
- newPosHdr->movesEnd= Umoves;
- }else{
- Umoves= newPosHdr->movesEnd;
- }
- #ifdef DEBUG
- repaint();
- Sleep(1);
- #endif
- break;
- }
- if(!memcmp(*u,newPos,posSize)){
- //pozice byla v tabulce nalezena
- found=HDR3(*u);
- if(found->dual!=isDual){
- newPosHdr->parent= curPos;
- if(isDual){
- UfoundPos=*u;
- UfoundPosD=newPos;
- }else{
- UfoundPosD=*u;
- UfoundPos=newPos;
- }
- return;
- }
- if(found->pus == newPosHdr->pus &&
- found->mov > newPosHdr->mov){
- //nalezeno lepÜφ °eÜenφ
- found->mov= newPosHdr->mov;
- found->parent= curPos;
- if(found->movesEnd > found->movesBeg){
- assert(newPosHdr->movesEnd-Umoves==found->movesEnd-found->movesBeg);
- memcpy(found->movesBeg,Umoves,(char*)newPosHdr->movesEnd-(char*)Umoves);
- }
- }
- break;
- }
- u++;
- if(u==hashTablek) u=hashTable;
- }
- }
- //vra¥ tah zp∞t
- curMove.next->obj= BM_GROUND;
- curMove.obj->obj= BM_OBJECT;
- }
- //sma₧ vÜechny objekty
- for(v=curPos+DXY; v<curPos+posSize1; v+=DXY){
- assert(i2p[rdXY(v)]->obj==BM_OBJECT);
- i2p[rdXY(v)]->obj=BM_GROUND;
- }
- if(UposTable==posTablek) break; //pam∞¥ u₧ je plnß
- }
- }
- //-------------------------------------------------------------------
- void addToHash(Pchar pos)
- {
- Pchar *u;
-
- u=hash(pos);
- while(*u){
- u++;
- if(u==hashTablek) u=hashTable;
- }
- *u=pos;
- }
- //-------------------------------------------------------------------
- void dijkstra()
- {
- int i,j,heapSize,foundEval,movpus1,x;
- Pchar *u,v,curPos,newPos;
- PHdr1 curPosHdr,newPosHdr,*heap,h;
- PMove Umoves,UmovesEnd,um;
- Psquare p,pn,pr,pnn;
- bool isDual;
-
- foundEval=0x7fffffff;
- //halda obsahuje ukazatele na pozice
- heap= new PHdr1[maxPos];
- //poΦßteΦnφ pozice
- curPos=UposTable;
- heap[curPosHdr->heapItem=heapSize=1]= curPosHdr= HDR1(curPos);
- curPosHdr->parent=0;
- curPosHdr->eval=0;
- curPosHdr->lastMove=0;
- curPosHdr->dual=false;
- addToHash(UposTable);
- UposTable+=posSize2;
- //sma₧ vÜechny objekty
- for(v=curPos+DXY; v<curPos+posSize1; v+=DXY){
- assert(i2p[rdXY(v)]->obj==BM_OBJECT);
- i2p[rdXY(v)]->obj=BM_GROUND;
- }
- //vφce koncov²ch pozic - vedle ka₧dΘho objektu
- for(j=0; j<Nstore; j++){
- p=fin2p[j];
- for(i=0; i<4; i++){
- pn=nxtP(p,i);
- if(pn->obj==BM_GROUND && !pn->store){
- pnn=nxtP(pn,i);
- if(pnn->obj==BM_GROUND && !pnn->store){
- memcpy(UposTable+DXY,finalPos,posSize1-DXY);
- wrXY0(UposTable,pn->i);
- h= HDR1(UposTable);
- heap[h->heapItem=++heapSize]=h;
- h->parent=0;
- h->eval=0;
- h->lastMove=0;
- h->dual=true;
- addToHash(UposTable);
- UposTable+=posSize2;
- }
- }
- }
- }
- Umoves=movedObj;
- //cyklus p°es vÜechny nalezenΘ pozice
- for( ;heapSize; ){
- //vezmi vrchol heapu - pozice s nejmenÜφm moves+pushes
- curPosHdr= heap[1];
- curPosHdr->heapItem=0;
- curPos= ((Pchar)curPosHdr)+DHDR1;
- isDual= curPosHdr->dual;
- //odstra≥ vrchol heapu
- x=heap[heapSize]->eval;
- j=1;
- i=2;
- while(i<heapSize){
- if(i+1 < heapSize && heap[i]->eval > heap[i+1]->eval) i++;
- if(x <= heap[i]->eval) break;
- heap[j]=heap[i];
- heap[j]->heapItem=j;
- j=i;
- i*=2;
- }
- heap[j]=heap[heapSize];
- heap[j]->heapItem=j;
- heapSize--;
- //vytvo° aktußlnφ pozici
- mover= i2p[rdXY(curPos)];
- for(v=curPos+DXY; v<curPos+posSize1; v+=DXY){
- assert(i2p[rdXY(v)]->obj==BM_GROUND);
- i2p[rdXY(v)]->obj=BM_OBJECT;
- }
- if(curPos==UfoundPos || curPos==UfoundPosD) goto end;
- //najdi vÜechny mo₧nΘ p°esuny v aktußlnφ pozici
- if(!isDual){
- UmovesEnd=findObjects(Umoves);
- }else{
- UmovesEnd=Umoves;
- p=mover;
- for(i=0; i<4; i++){
- pn=nxtP(p,i);
- if(pn->obj==BM_OBJECT){
- pr=prvP(p,i);
- if(pr->obj==BM_GROUND){
- mover=pr;
- p->obj=BM_OBJECT;
- pn->obj=BM_GROUND;
- UmovesEnd=findObjectsD(UmovesEnd,pn,i);
- pn->obj=BM_OBJECT;
- p->obj=BM_GROUND;
- }
- }
- }
- mover=p;
- }
- if(!isDual){
- um= testLastMove(curPosHdr->lastMove, Umoves);
- if(um) UmovesEnd=um;
- }else{
- testLastMoveD(curPosHdr->lastMove,Umoves,UmovesEnd);
- }
- if(1 || !testBlocked(curPos, curPosHdr->lastMove, UmovesEnd)){
- for(; Umoves<UmovesEnd; Umoves++){
- newPos=UposTable;
- if(newPos==posTablek) break;
- newPosHdr=HDR1(newPos);
- assert(testPos(curPos));
- //prove∩ tah
- Move &curMove= *Umoves;
- if(curMove.direct<0) continue;
- assert(curMove.obj->obj==BM_OBJECT);
- curMove.obj->obj= BM_GROUND;
- mover= curMove.obj;
- if(isDual){
- mover= curMove.next;
- curMove.next= prvP(curMove.obj,curMove.direct);
- }
- assert(curMove.next->obj==BM_GROUND);
- curMove.next->obj= BM_OBJECT;
- if(isDual || !testDead(curMove.next)){
- //vytvo° novou pozici
- makeMove(newPos,curPos,curMove);
- wrXY0(newPos,mover->i);
- movpus1= curPosHdr->eval + curMove.dist + 1;
- //vypoΦti hashovacφ funkci
- u=hash(newPos);
- for(;;){
- if(!*u){
- //p°idej novou pozici do tabulky
- *u=newPos;
- newPosHdr->dual=isDual;
- UposTable+=posSize2;
- //zv∞tÜi velikost heapu
- newPosHdr->heapItem= ++heapSize;
- #ifdef DEBUG
- repaint();
- Sleep(1);
- #endif
- break;
- }
- if(rdXY(*u)==rdXY(newPos) && !memcmp(*u,newPos,posSize)){
- //pozice byla v tabulce nalezena
- h=HDR1(*u);
- //test setkßnφ dop°ednΘho a dußlnφho °eÜenφ
- if(h->dual!=isDual){
- if(!h->heapItem && movpus1+h->eval < foundEval){///
- foundEval= movpus1+h->eval;
- if(isDual){
- UfoundPos=*u;
- UfoundPosD=curPos;
- }else{
- UfoundPosD=*u;
- UfoundPos=curPos;
- }
- }
- goto nxt;
- }
- newPos=*u;
- newPosHdr= HDR1(newPos);
- assert(!newPosHdr->parent || newPosHdr->parent>=posTable && newPosHdr->parent<posTablek);
- if(newPosHdr->eval <= movpus1) goto nxt;
- //nalezeno lepÜφ °eÜenφ
- break;
- }
- u++;
- if(u==hashTablek) u=hashTable;
- }
- //oprav set°φd∞nφ heapu
- newPosHdr->parent= curPos;
- newPosHdr->eval= movpus1;
- newPosHdr->lastMove= &curMove;
- j= newPosHdr->heapItem;
- i=j/2;
- while(i>0 && heap[i]->eval > movpus1){
- heap[j]=heap[i];
- heap[j]->heapItem=j;
- j=i;
- i/=2;
- }
- heap[j]= newPosHdr;
- newPosHdr->heapItem=j;
- }
- nxt:
- //vra¥ tah zp∞t
- curMove.next->obj= BM_GROUND;
- curMove.obj->obj= BM_OBJECT;
- }
- }
- //sma₧ vÜechny objekty
- for(v=curPos+DXY; v<curPos+posSize1; v+=DXY){
- assert(i2p[rdXY(v)]->obj==BM_OBJECT);
- i2p[rdXY(v)]->obj=BM_GROUND;
- }
- if(UposTable==posTablek) break;
- }
- end:
- delete[] heap;
- if(UfoundPos){
-
- }
- }
- //-------------------------------------------------------------------
- void delBlind()
- {
- Psquare p,pn,pn1;
- int i,j,i1;
-
- //sma₧ slepΘ uliΦky
- UfirstMove= firstMove= new char[width*height/2];
- for(p=board; p<boardk; p++){
- if(p->obj==BM_GROUND && !p->store){
- j=0;
- for(i=0; i<4; i++){
- pn=nxtP(p,i);
- if(pn->obj!=BM_WALL){
- j++;
- pn1=pn;
- i1=i;
- }
- }
- if(j==1){
- if(p==mover){
- if(pn1->obj==BM_OBJECT){
- if(nxtP(pn1,i1)->obj!=BM_GROUND || pn1->store){
- continue;
- }
- pn1->obj=BM_GROUND;
- nxtP(pn1,i1)->obj=BM_OBJECT;
- *UfirstMove++ = char('4'+i1);
- }else{
- *UfirstMove++ = char('0'+i1);
- }
- mover=pn1;
- }
- p->obj=BM_WALL;
- p=board;
- }
- }
- }
- }
- //-------------------------------------------------------------------
- int thinkInit()
- {
- Psquare p,pn,pnn,*p1,*p2,*pf,*ps,po[4];
- int i,j,jm,m,d,k,w,*UfinA,*finRadius;
- Pchar UfinalPos,UstartPos;
-
- Nobj=Nstore=i=0;
- for(p=board; p<boardk; p++){
- if(p->obj==BM_GROUND || p->obj==BM_OBJECT){
- p->i=i++;
- for(j=0; j<4; j++){
- po[j]=nxtP(p,j);
- p->cont[j]=-1;
- }
- if(po[0]->obj!=BM_WALL && po[1]->obj!=BM_WALL &&
- po[2]->obj==BM_WALL && po[3]->obj==BM_WALL){
- p->cont[0]=p->cont[1]=1;
- }
- else if(po[0]->obj==BM_WALL && po[1]->obj==BM_WALL &&
- po[2]->obj!=BM_WALL && po[3]->obj!=BM_WALL){
- p->cont[2]=p->cont[3]=1;
- }
- }else{
- p->i=-1;
- }
- if(p->obj==BM_OBJECT) Nobj++;
- if(p->store) Nstore++;
- p->distId=0;
- }
- Nground=i;
- UfinA= finalDistA= new int[i*Nstore];
- i2p= new Psquare[i];
- fin2p= new Psquare[Nstore+1];
- DXY=1;
- if(i>255) DXY=sizeof(WORD);
- if(Nobj) maxPos= maxMem*1000000/4/sizeof(Move)/Nstore;
- aminmax(maxPos,100,maxPos0);
- const int D[]={DHDR2,DHDR3,DHDR1,DHDR4};
- DHDR= D[algorithm];
- distId=0;
- posSize1= posSize= (Nobj+1)*DXY;
- posSize2= posSize1+DHDR;
- DhashTable= maxPos*2+17;
- hashTable= new char*[DhashTable];
- hashTablek= hashTable+DhashTable;
- posTable= new char[maxPos*posSize2];
- UposTable= posTable+DHDR;
- posTablek= UposTable + maxPos*posSize2;
- UfoundPos=UfoundPosD=0;
- testing=0;
- finalDone=0;
- if(!posTable){
- noMem();
- movedObj=0;
- finalPos=0;
- return 1;
- }
- memset(hashTable,0,DhashTable*sizeof(*hashTable));
-
- //poΦßteΦnφ a koncovß pozice
- UfinalPos= finalPos= new char[Nstore*DXY];
- p1=distBuf1;
- p2=distBuf2;
- UstartPos= UposTable;
- wrXY(UstartPos, mover->i);
- pf=fin2p;
- for(p=board; p<boardk; p++){
- p->finalDist=MAXDIST;
- if(p->store){
- p->finalDist=0;
- *p1++=p;
- *p2++=p;
- *pf++=p;
- wrXY(UfinalPos,p->i);
- }
- if(p->obj==BM_OBJECT){
- wrXY(UstartPos,p->i);
- }
- if(p->i!=-1){
- i2p[p->i]=p;
- p->finalDists= UfinA;
- UfinA += Nstore;
- p->direct=-1;
- for(j=0; j<4; j++){
- if((prvP(p,j)->cont[j]&-2)==0 &&
- p->cont[j]==-1 && !p->store &&
- (nxtP(p,j^2)->obj==BM_WALL || nxtP(p,j^3)->obj==BM_WALL)){
- p->cont[j]=2;
- }
- if(p->cont[j]==1 &&
- (p->store || (prvP(p,j)->cont[j]&-2))){
- p->cont[j]=0;
- }
- }
- }
- }
- assert(UfinA==finalDistA+Nground*Nstore);
- //po°adφ koncov²ch polφΦek
- *p1=*p2=0;
- ps=distBuf2;
- for(d=Nstore; *ps && d>=0; d--){
- for(p1=ps; *p1; p1++){
- for(i=0; i<4; i++){
- pn= nxtP(*p1,i);
- pnn= nxtP(pn,i);
- if(pn->obj!=BM_WALL && pnn->obj!=BM_WALL &&
- pn->finalDist>d && pnn->finalDist>d){
- (*p1)->finalDist=d;
- *p1=*ps++;
- break;
- }
- }
- }
- }
- //v²poΦet finalDist
- for(d=(Nstore+1)|1; ; d++){
- if(d&1) p1=distBuf1,p2=distBuf2;
- else p1=distBuf2,p2=distBuf1;
- if(!*p1) break;
- for( ; *p1; p1++){
- for(i=0; i<4; i++){
- pn= nxtP(*p1,i);
- pnn= nxtP(pn,i);
- if(pn->finalDist>=MAXDIST && pn->obj!=BM_WALL && pnn->obj!=BM_WALL
- && pn->obj!=BM_BACKGROUND){
- pn->finalDist=d;
- *p2++=pn;
- }
- }
- }
- *p2=0;
- }
- //vypoΦti finalDists[j]
- for(p1=fin2p; p1<fin2p+Nstore; p1++){
- (*p1)->finalDist=0;
- }
- finRadius= new int[Nstore];
- for(k=Nstore; k; ){
- for(j=0; j<k; j++){
- for(p1=i2p; p1<i2p+Nground; p1++){
- (*p1)->finalDists[j]=MAXDIST;
- }
- p=fin2p[j];
- distBuf1[0]=p;
- distBuf1[1]=0;
- p->finalDists[j]=0;
- for(d=(Nstore+1)|1; ; d++){
- if(d&1) p1=distBuf1,p2=distBuf2;
- else p1=distBuf2,p2=distBuf1;
- if(!*p1) break;
- for( ; *p1; p1++){
- for(i=0; i<4; i++){
- pn= nxtP(*p1,i);
- pnn= nxtP(pn,i);
- if(pn->obj!=BM_WALL && pn->obj!=BM_BACKGROUND &&
- pn->finalDists[j]>=MAXDIST &&
- pnn->obj!=BM_WALL &&
- pn->finalDist>=k && pnn->finalDist>=k){
- pn->finalDists[j]=d;
- *p2++=pn;
- }
- }
- }
- *p2=0;
- }
- finRadius[j]=d;
- }
- m=MAXDIST;
- jm=0;
- for(j=0; j<k; j++){
- if(finRadius[j]<=m && finRadius[j] > Nstore+5 &&
- (finRadius[j]<m || k==Nstore ||
- fin2p[k]->finalDists[j] < fin2p[k]->finalDists[jm])){
- m=finRadius[j];
- jm=j;
- }
- }
- k--;
- p=fin2p[jm];
- fin2p[jm]=fin2p[k];
- fin2p[k]=p;
- p->finalDist=k;
- for(p1=i2p; p1<i2p+Nground; p1++){
- p=*p1;
- w= p->finalDists[k];
- p->finalDists[k]= p->finalDists[jm];
- p->finalDists[jm]= w;
- if(p->finalDist<k) p->finalDists[k]=0;
- }
- }
- fin2p[Nstore]= board;
- delete[] finRadius;
- assert(testPos(UposTable));
- if(!memcmp(finalPos,UposTable+DXY,posSize1-DXY)){
- UfoundPos=UfoundPosD=UposTable;
- }
- movedObj= new Move[Nobj*4*maxPos];
- if(!movedObj){
- noMem();
- return 1;
- }
- return 0;
- }
- //-------------------------------------------------------------------
- void thinkDestroy()
- {
- delete[] movedObj;
- delete[] finalPos;
- delete[] posTable;
- delete[] hashTable;
- delete[] fin2p;
- delete[] i2p;
- delete[] finalDistA;
- delete[] firstMove; firstMove=0;
- }
- //-------------------------------------------------------------------
- void gener()
- {
- Pchar *u,v,curPos,newPos;
- PHdr4 curPosHdr,newPosHdr;
- PMove Umoves,Umoves1;
- Psquare *pp;
-
- algorithm=3;
- if(thinkInit()){
- thinkDestroy();
- return;
- }
- curPos= UposTable;
- curPosHdr=HDR4(curPos);
- curPosHdr->mov=curPosHdr->pus=0;
- curPosHdr->movesBeg= movedObj;
- curPosHdr->movesEnd= Umoves= findObjectsR(movedObj);
- for(v=curPos+DXY; v<curPos+posSize1; v+=DXY){
- assert(i2p[rdXY(v)]->obj==BM_OBJECT);
- i2p[rdXY(v)]->obj=BM_GROUND;
- }
- UposTable+=posSize2;
- for( ;curPos<UposTable; curPos+=posSize2){
- curPosHdr= HDR4(curPos);
- //vytvo° aktußlnφ pozici
- for(v=curPos+DXY; v<curPos+posSize1; v+=DXY){
- assert(i2p[rdXY(v)]->obj==BM_GROUND);
- i2p[rdXY(v)]->obj=BM_OBJECT;
- }
- for(Umoves1=curPosHdr->movesBeg; Umoves1<curPosHdr->movesEnd; Umoves1++){
- Move &curMove= *Umoves1;
- newPos=UposTable;
- if(newPos==posTablek) break;
- newPosHdr=HDR4(newPos);
- //prove∩ tah
- assert(testPos(curPos));
- assert(curMove.next->obj==BM_GROUND);
- assert(curMove.obj->obj==BM_OBJECT);
- curMove.next->obj= BM_OBJECT;
- curMove.obj->obj= BM_GROUND;
- //vytvo° novou pozici
- mover= prvP(curMove.next,curMove.direct);
- //najdi vÜechny mo₧nΘ p°esuny v novΘ pozici
- newPosHdr->movesEnd= findObjectsR(Umoves);
- if(newPosHdr->movesEnd>Umoves){
- makeMove(newPos,curPos,curMove);
- newPosHdr->mov= (short)(curPosHdr->mov + curMove.dist);
- newPosHdr->pus= (short)(curPosHdr->pus + 1);
- //hrßΦe dej do levΘho hornφho rohu
- for(pp=i2p; (*pp)->distId!=distId; pp++) ;
- wrXY0(newPos,(*pp)->i);
- //vypoΦti hashovacφ funkci
- u=hash(newPos);
- for(;;){
- if(!*u){
- //p°idej novou pozici do tabulky
- *u=newPos;
- UposTable+=posSize2;
- newPosHdr->movesBeg= Umoves;
- Umoves= newPosHdr->movesEnd;
- #ifdef DEBUG
- repaint();
- #endif
- break;
- }
- if(!memcmp(*u,newPos,posSize1)){
- //pozice byla v tabulce nalezena
- break;
- }
- u++;
- if(u==hashTablek) u=hashTable;
- }
- }
- //vra¥ tah zp∞t
- curMove.next->obj= BM_GROUND;
- curMove.obj->obj= BM_OBJECT;
- }
- //sma₧ vÜechny objekty
- for(v=curPos+DXY; v<curPos+posSize1; v+=DXY){
- assert(i2p[rdXY(v)]->obj==BM_OBJECT);
- i2p[rdXY(v)]->obj=BM_GROUND;
- }
- }
- //nastav poslednφ nalezenou pozici
- curPos=UposTable-posSize2;
- curPosHdr=HDR4(curPos);
- mover= i2p[rdXY(curPos)];
- for(v=curPos+DXY; v<curPos+posSize1; v+=DXY){
- i2p[rdXY(v)]->obj=BM_OBJECT;
- }
- repaint();
- msg("%d-%d\n%d", curPosHdr->mov, curPosHdr->pus,
- (UposTable-posTable)/posSize2);
- thinkDestroy();
- edUndo=edRec; edRedo=0;
- }
- //-------------------------------------------------------------------
- //p°emφsti se ze src na dest
- void wrSolPath(Psquare src, Psquare dest)
- {
- Psquare p,pn;
- int i;
-
- if(!src) return;
- findDist(dest,src);
- assert(src->distId==distId);
- for(p=src; p!=dest; p=pn){
- for(i=0; ; i++){
- pn=nxtP(p,i);
- if(pn->dist==p->dist-1) break;
- }
- *UfoundSol++= (char) (i+'0');
- }
- }
- //-------------------------------------------------------------------
- Pchar getParent(Pchar pos)
- {
- switch(algorithm){
- case 0:
- return HDR2(pos)->parent;
- case 1:
- return HDR3(pos)->parent;
- case 2:
- return HDR1(pos)->parent;
- }
- return 0;
- }
- //-------------------------------------------------------------------
- void wrSol()
- {
- Pchar u,prv,v,v1,v2,foundSol;
- Psquare p,pn,moverS=0;
- int d,direct,dual;
-
- //zapiÜ tahy vzniklΘ smazßnφm slep²ch uliΦek
- logPos=logbuf;
- for(u=firstMove; u<UfirstMove; u++){
- wrLog(*u);
- }
- //alokuj buffer pro v²sledek
- switch(algorithm){
- case 0:
- d=HDR2(UfoundPos)->eval;
- break;
- case 1:
- d=HDR3(UfoundPos)->mov+HDR3(UfoundPosD)->mov+Nground;
- break;
- case 2:
- d=HDR1(UfoundPos)->eval+HDR1(UfoundPosD)->eval+Nground;
- break;
- }
- foundSol= new char[d+1];
-
- for(dual=0; dual<2; dual++){
- UfoundSol=foundSol;
- //sma₧ objekty
- for(p=board; p<boardk; p++){
- if(p->obj==BM_OBJECT) p->obj=BM_GROUND;
- }
- //nastav pozici
- u= dual ? UfoundPosD:UfoundPos;
- if(!u) break;
- for(v=u+DXY; v<u+posSize1; v+=DXY){
- i2p[rdXY(v)]->obj=BM_OBJECT;
- }
- mover=0;
- if(dual) mover=moverS;
-
- //projdi pozice sm∞rem k poΦßteΦnφ nebo koncovΘ
- for(; (prv=getParent(u))!=0; u=prv){
- //zjisti sm∞r p°esunu mezi pozicemi prv, u
- for(v1=prv+DXY,v2=u+DXY; rdXY(v1)==rdXY(v2); v1+=DXY,v2+=DXY) ;
- d= rdXY(v2)-rdXY(v1);
- if(d>0){
- if(d!=1 || v1+DXY<prv+posSize1 && rdXY(v1+DXY)==rdXY(v2)){
- direct=2;
- }else{
- direct=0;
- }
- p=i2p[rdXY(v1)];
- pn=prvP(p,direct);
- if(pn->obj!=BM_OBJECT){
- assert(direct==0 && pn->obj==BM_WALL);
- pn=prvP(p,direct=2);
- }
- }else{
- if(d!=-1 || v2+DXY<u+posSize1 && rdXY(v1)==rdXY(v2+DXY)){
- direct=3;
- }else{
- direct=1;
- }
- pn=i2p[rdXY(v2)];
- p=nxtP(pn,direct);
- if(p->obj!=BM_GROUND){
- assert(direct==1);
- p=nxtP(pn,direct=3);
- }
- }
- //p°emφsti se k objektu
- wrSolPath(mover, dual ? prvP(pn,direct) : p);
- if(u==UfoundPos) moverS=p;
- //prove∩ p°esun z pn na p
- assert(pn->obj==BM_OBJECT);
- assert(p->obj==BM_GROUND);
- pn->obj=BM_GROUND;
- p->obj=BM_OBJECT;
- mover= dual ? pn : nxtP(p,direct);
- *UfoundSol++= (char) (direct+'4');
- }
- if(!dual){
- wrSolPath(mover, i2p[rdXY(posTable+DHDR)]);
- //prvnφ polovina °eÜenφ - obrßcen∞
- for(u=UfoundSol-1; u>=foundSol; u--){
- wrLog(char(*u^1));
- }
- if(algorithm==2){
- HDR1(UfoundPos)->parent=UfoundPosD;
- UfoundPosD=UfoundPos;
- }
- }else{
- //druhß polovina °eÜenφ
- for(u=foundSol; u<UfoundSol; u++){
- wrLog(*u);
- }
- }
- }
- delete[] foundSol;
- *logPos=0;
- logPos=0;
- }
- //-------------------------------------------------------------------
- int findSolution(int alg)
- {
- int k;
- DWORD time= GetTickCount();
-
- algorithm=alg;
- delBlind();
- if(thinkInit()){
- thinkDestroy();
- return -4;
- }
- if(Nobj!=Nstore || !Nobj) return -3;
- switch(algorithm){
- case 0:
- depthSearch();
- break;
- case 1:
- breadthSearch();
- break;
- case 2:
- dijkstra();
- break;
- }
- assert(UposTable<=posTablek);
- if(UfoundPos){
- //zapiÜ a "zkomprimuj" °eÜenφ
- wrSol();
-
- ///assert(algorithm!=2 || mov+pus==HDR1(UfoundPos)->eval);
- //if(algorithm==1) msg("%d-%d, %d-%d",HDR3(UfoundPos)->mov,HDR3(UfoundPos)->pus,HDR3(UfoundPosD)->mov,HDR3(UfoundPosD)->pus);
- }
- thinkDestroy();
- time=GetTickCount()-time;
- if(UfoundPos){
- loadSolution(level, logbuf);
- assert(!movError);
- //zapsßnφ °eÜenφ do databßze
- finish();
- saveUser();
- saveData();
- status();
- if(gratulOn){
- k= int(((char*)UposTable-(char*)posTable)/posSize2);
- msg("Solution: %d-%d\nTime: %d ms\n\nPositions: %d, %d",
- moves,pushes, time, k, maxPos - int(((char*)posTablek-(char*)UposTable)/posSize2) - k);
- }
- return moves+pushes;
- }else{
- resetLevel();
- }
- if(UposTable==posTablek){
- if(gratulOn){
- k= int((char*)UposTable-(char*)posTable)/posSize2;
- msg("Timeout: %d ms\n\nPositions: %u, %u",
- time, k, maxPos - k);
- }
- return -1;
- }
- msg("Unsolvable");
- return -2;
- }
- //-------------------------------------------------------------------
-
-